#include "stdafx.h"

//--------------------------------------------------------------------------------------
CTimer::CTimer( )
{
	_TimeIsStopped     = true;
	_StopTicks        = 0;
	_StartTicks        = 0;
	_Counter = 0;
	// Use QueryPerformanceFrequency to get the frequency of the counter
	LARGE_INTEGER qwTicksPerSec;
	QueryPerformanceFrequency( &qwTicksPerSec );
	_TicksPerSec = qwTicksPerSec.QuadPart;
}

//--------------------------------------------------------------------------------------
void CTimer::Start( )
{
	if(_Counter > 0) --_Counter;
	if(_Counter == 0){
		LARGE_INTEGER qwTicks;
		QueryPerformanceCounter( &qwTicks );
		_StartTicks = qwTicks.QuadPart;
		_StopTicks = 0;
		_TimeIsStopped = false;
	}
}

//--------------------------------------------------------------------------------------
void CTimer::Stop( )
{
	++_Counter;
	if( !_TimeIsStopped )
	{
		_StopTicks = GetTicksSinceStart();
		_TimeIsStopped = true;
	}
}

//--------------------------------------------------------------------------------------
void CTimer::Reset( )
{
	LARGE_INTEGER qwTicks;
	QueryPerformanceCounter( &qwTicks );
	_StartTicks        = qwTicks.QuadPart;
	_StopTicks        = 0;
	_TimeIsStopped     = false;
	_Counter = 0;
}

//--------------------------------------------------------------------------------------
double CTimer::GetSystemTime( )
{
	LARGE_INTEGER qwTicks;
	QueryPerformanceCounter( &qwTicks );
	double fTime = qwTicks.QuadPart / (double) _TicksPerSec;
	return fTime;
}

double CTimer::GetElapsedTimeBySystem(LONGLONG& LastTicks_io)
{
	LARGE_INTEGER qwTicks;
	QueryPerformanceCounter( &qwTicks );
	double fElapsedTime = (double) ( qwTicks.QuadPart - LastTicks_io ) / (double) _TicksPerSec;
	LastTicks_io = qwTicks.QuadPart;
	// See the explanation about clamping in CTimer::GetTimeValues( )
	if( fElapsedTime < 0.0f )
		fElapsedTime = 0.0f;
	return fElapsedTime;
}

//--------------------------------------------------------------------------------------
double CTimer::GetTimeSinceStart( )
{
	LONGLONG qwTicks = GetTicksSinceStart( );
	double fAppTime = (double) qwTicks / (double) _TicksPerSec;
	return fAppTime;
}

//--------------------------------------------------------------------------------------
double CTimer::GetElapsedTimeByTimer(LONGLONG& LastTicks_io)
{
	LONGLONG qwTicks = GetTicksSinceStart( );
	double fElapsedTime = (double) ( qwTicks - LastTicks_io ) / (double) _TicksPerSec;
	LastTicks_io = qwTicks;
	// See the explanation about clamping in CTimer::GetTimeValues( )
	if( fElapsedTime < 0.0f )
		fElapsedTime = 0.0f;
	return fElapsedTime;
}

//--------------------------------------------------------------------------------------
// If stopped, returns time when stopped otherwise returns current time
//--------------------------------------------------------------------------------------
LONGLONG CTimer::GetTicksSinceStart( )
{
	if(_TimeIsStopped) 
		return _StopTicks - _StartTicks;

	LARGE_INTEGER qwTicks;
	QueryPerformanceCounter( &qwTicks );
	qwTicks.QuadPart -= _StartTicks;
	return qwTicks.QuadPart;
}

//--------------------------------------------------------------------------------------
bool CTimer::IsStopped( )
{
	return _TimeIsStopped;
}

//--------------------------------------------------------------------------------------
// Limit the current thread to one processor (the current one). _this ensures that timing code 
// runs on only one processor, and will not suffer any ill effects from power management.
// See "Game Timing and Multicore Processors" for more details
//--------------------------------------------------------------------------------------
void CTimer::LimitThreadAffinityToCurrentProc( )
{
	HANDLE hCurrentProcess = GetCurrentProcess( );

	// Get the processor affinity mask for this process
	DWORD_PTR dwProcessAffinityMask = 0;
	DWORD_PTR dwSystemAffinityMask = 0;

	if( GetProcessAffinityMask( hCurrentProcess, &dwProcessAffinityMask, &dwSystemAffinityMask ) != 0 && dwProcessAffinityMask )
	{
		// Find the lowest processor that our process is allows to run against
		DWORD_PTR dwAffinityMask = ( dwProcessAffinityMask & ((~dwProcessAffinityMask) + 1 ) );
		// Set this as the processor that our thread must always run against
		// _this must be a subset of the process affinity mask
		HANDLE hCurrentThread = GetCurrentThread( );
		if( INVALID_HANDLE_VALUE != hCurrentThread )
		{
			SetThreadAffinityMask( hCurrentThread, dwAffinityMask );
			CloseHandle( hCurrentThread );
		}
	}
	CloseHandle( hCurrentProcess );
}
